# coding:utf-8
'''策略文件

最近的盘中结束
[美股]
盘前：16:00-21:30
盘中：21:30-04:00,
盘后：04:00-08:00

[港股]
盘前：
9:00-9:15(竞价时段)
9:15-9:20(对盘钱时段)
9:20-9:30(暂停时段)

盘中：
上午：9:30-12:00
下午：13:00-16:08-16:10(随机)

[A股]
上午：9:30-11:30
下午：13:00-15:00
'''

import sys

# if 'linux' in sys.platform:
#     sys.path.append('/root/lianghua/后台_实盘交易/')
# else:
#     sys.path.append('..')

from futu import *
from module.data.FutuAPI2 import get_stock_type
import datetime
from module.common.Config import redis_local_auth
from module.common import Config
from module.common.common import strTime_to_timestamp,get_vail_sellTime_2,sendEmail,Except_stop
import re
from module.utils import TaskAdminUtil
import pymysql

# middle_closeTime = '12:30:00'
# down_closeTime = '16:00:00'
#
# HK_openTime = '9:30:00'
# A_openTime = '9:30:00'
# US_openTime = '21:30:00'
#
# clash_col = ['failure_time','Before_after_run','way','bs_direction','buyPrice','count']  # 冲突字段

# basePath = '/root/processLog/' + sys.argv[0][sys.argv[0].rfind(os.sep) + 1:].replace('.py', '.log')
# logger = Logger(log_file_name=basePath, log_level=logging.DEBUG, logger_name="test").get_log()


def conn_local_redis(db=0):
    import redis
    r = redis.Redis(host='127.0.0.1', password=redis_local_auth, decode_responses=True,db=db)
    return r
local_r = conn_local_redis()
local_res = conn_local_redis(db=3)


# 下单后全部已成写入数据库
def save_tradeDetail(data):
    conn = pymysql.connect(host=Config.sql_host, user=Config.sql_user, password=Config.sql_pass, db='money',
                                 port=Config.sql_port)
    cur=conn.cursor()

    sql = f'''INSERT INTO `tbl_trade_detail_t` (`trd_side`, `order_type`, `order_status`, `order_id`, `code`, `stock_name`,
     `qty`, `price`, `create_time`, `updated_time`, `dealt_qty`, `dealt_avg_price`, `last_err_msg`, `remark`, `acc_id`) VALUES 
     {data};'''
    cur.execute(sql)
    conn.commit()
    cur.close()
    conn.close()

def pushSql_to_redis(sql):
    local_res.rpush('backtest_res', str(['simulate_real', sql]))


# 文字-符号转换
opt_transfor = {'大于':'>', '小于':'<', '等于':'==', '大于等于':'>=', '小于等于':'<='}
class Strategy_group:
    def __init__(self, ifTest=False):
        self.ifTest = ifTest

    # 当前市价: 正股,个股对比,期权
    def STK_01(self, item, price,high_price,low_price, stock_name=''):
        '''当前市价'''
        itemValue = item['itemValue']
        if item['bItem']=='指定价格':
            execStr = f'{price} {opt_transfor[item["cItem"]]} {itemValue}'
            logStr = f'{stock_name},当前市价{item["cItem"]} {itemValue}({price})'
        elif item['bItem']=='是否最高最低价':
            if item['cItem'] == '最高价':
                execStr = f'{price}=={high_price}'
                logStr = f'{stock_name},当前市价为最高价{high_price}（{price}）'
            elif item['cItem'] == '最低价':
                execStr = f'{price}=={low_price}'
                logStr = f'{stock_name},当前市价为最低价{low_price}（{price}）'
            else:
                execStr = f'1==0'
                logStr = f'{item["aItem"]}策略选项异常，请检查'
        else:
            execStr = f'1==0'
            logStr = f'{item["aItem"]}策略选项异常，请检查'
        return execStr,logStr

    # 市价涨跌：正股,个股对比,期权
    def STK_02(self, item,UD,UDP, stock_name=''):
        itemValue = item['itemValue']
        opt_transfor_02 = {'涨以上':'>','涨以下':'<','涨等于':'==','涨等于以上':'>=','涨等于以下':'<=',
                           '跌以上':'<-','跌以下':'>-','跌等于':'==-','跌等于以上':'<=-','跌等于以下':'>=-'}
        if item['bItem'] == '涨跌额':
            execStr = f'{UD}{opt_transfor_02[item["cItem"]+item["dItem"]]}{itemValue}'
            logStr = f'{stock_name},市价涨跌,涨跌额,{item["cItem"]+item["dItem"]}{itemValue}（{UD}）'
        elif item['bItem'] == '涨跌幅':
            execStr = f'{UDP}{opt_transfor_02[item["cItem"] + item["dItem"]]}{itemValue}'
            logStr = f'{stock_name},市价涨跌,涨跌幅,{item["cItem"] + item["dItem"]}{itemValue}（{UDP}）'
        else:
            execStr = f'1==0'
            logStr = f'{item["aItem"]}策略选项异常，请检查'
        return execStr, logStr

    # 成交额：正股，个股对比
    def STK_03(self, item,code, turnover,r, stock_name=''):
        # 美股非期权的成交额获取
        if 'US.' in code and len(code) < 11 and self.ifTest==False:
            if r.hexists('usRealTurnover', code):
                turnover = float(r.hget('usRealTurnover', code))
            else:
                return [False], '成交额为0 X.'
        else:
            turnover = turnover

        label = item['label_value'].replace(':', '')  # 单位
        itemValue = item['itemValue']
        turnover = round(turnover / 100000000, 2) if label == '亿' else round(turnover / 10000, 2)

        try:
            execStr = f'{turnover} {opt_transfor[item["bItem"]]}{itemValue}'
            logStr = f'{stock_name},当前成交额{opt_transfor[item["bItem"]]}{itemValue}{label}（{turnover}){label}）'
        except:
            execStr = f'1==0'
            logStr = f'{item["aItem"]}策略选项异常，请检查'
        return execStr, logStr

    # 单次盈亏：正股，期权
    def STK_04(self, item, code, last_price, num, orderBuyPrice, O_name, stock_name=''):
        itemValue = item['itemValue']

        # 盈亏金额 （实时价格 - 买入价格) * 股数
        one_pnle = (last_price - orderBuyPrice) * int(num)
        # 盈亏比率 盈亏金额/买入价格*股本 * 100%
        one_pnlfu = one_pnle / (orderBuyPrice * int(num)) * 100
        if len(code) > 10:
            one_pnle = one_pnle * 100
            one_pnlfu = one_pnlfu

        one_pnle = round(one_pnle, 3)  # 盈亏金额
        one_pnlfu = round(one_pnlfu, 3)  # 盈亏幅度

        if item['bItem'] == '金额':  # 金额
            if item['cItem'] == '盈利':  # 盈利
                execStr = f'{one_pnle}>{itemValue}'
                logStr = f'{stock_name} 市价{last_price}, 单次盈亏,金额大于{itemValue}（{one_pnle}）'
            elif item['cItem'] == '亏损':  # 亏损
                execStr = f'{one_pnle}<-{itemValue}'
                logStr = f'{stock_name} 市价{last_price}, 单次盈亏,金额小于-{itemValue}（{one_pnle}）'
            else:
                execStr = f'1==0'
                logStr = f'{item["aItem"]} 策略选项异常，请检查'
        elif item['bItem'] == '幅度':  # 幅度
            if item['cItem'] == '盈利':  # 盈利
                execStr = f'{one_pnlfu}>{itemValue}'
                logStr = f'{stock_name} 市价{last_price}, 单次盈亏,幅度大于{itemValue}%（{one_pnlfu}%）'
            elif item['cItem'] == '亏损':  # 亏损
                execStr = f'{one_pnlfu}<-{itemValue}'
                logStr = f'{stock_name} 市价{last_price}, 单次盈亏,幅度小于-{itemValue}%（{one_pnlfu}%）'
                if one_pnlfu < -itemValue and '_配置项' in O_name:
                    return [True], logStr + '√.(终止)'
            else:
                execStr = f'1==0'
                logStr = f'{item["aItem"]} 策略选项异常，请检查'
        else:
            execStr = f'1==0'
            logStr = f'{item["aItem"]} 策略选项异常，请检查'
        return execStr,logStr

    # 持仓盈亏：正股，期权
    def STK_05(self, item, r, code, last_price, preClose, TrdEnv, acc_id, stock_name=''):
        itemValue = item['itemValue']
        cal_pl_val, cal_pl_ratio, today_pl_val, qty = self.position_data(r, code , last_price, preClose, TrdEnv, acc_id)  # 请求持仓的数据

        if qty == 0:
            return [False], '没有持仓不存在盈亏金额X.</br>'

        # if order_direction==0:  # 买入方向和原来保持不变，亏损抄底
        if item['bItem'] == '金额':  # 金额
            if item['cItem'] == '盈利':  # 盈利
                execStr = f'{cal_pl_val}>{itemValue}'
                logStr = f'{stock_name},持仓盈亏,金额大于{itemValue}（{cal_pl_val}）'
            elif item['cItem'] == '亏损':  # 亏损
                execStr = f'{cal_pl_val}<-{itemValue}'
                logStr = f'{stock_name},持仓盈亏,金额小于-{itemValue}（{cal_pl_val}）'
            else:
                execStr = f'1==0'
                logStr = '策略选项异常，请检查'
        elif item['bItem'] == '幅度':  # 幅度
            if item['cItem'] == '盈利':  # 盈利
                execStr = f'{cal_pl_ratio}>{itemValue}'
                logStr = f'{stock_name},持仓盈亏,幅度大于{itemValue}%（{cal_pl_ratio}%）'
            elif item['cItem'] == '亏损':  # 亏损
                execStr = f'{cal_pl_ratio}<-{itemValue}'
                logStr = f'{stock_name},持仓盈亏,幅度小于-{itemValue}%（{cal_pl_ratio}%）'
            else:
                execStr = f'1==0'
                logStr = '策略选项异常，请检查'
        else:
            execStr = f'1==0'
            logStr = '策略选项异常，请检查'
        return execStr,logStr

    # 今日持仓盈亏：正股，期权
    def STK_06(self, item, r, code, last_price, preClose, TrdEnv, acc_id, stock_name=''):
        itemValue = item['itemValue']
        cal_pl_val, cal_pl_ratio, today_pl_val, qty = self.position_data(r, code, last_price, preClose, TrdEnv,
                                                                         acc_id)  # 请求持仓的数据

        if qty == 0:
            return [False], '没有持仓不存在盈亏金额X.</br>'

        if item['bItem'] == '金额':  # 金额
            if item['cItem'] == '盈利':  # 盈利
                execStr = f'{today_pl_val}>{itemValue}'
                logStr = f'{stock_name},今日持仓盈亏,金额大于{itemValue}（{today_pl_val}）'
            elif item['cItem'] == '亏损':  # 亏损
                execStr = f'{today_pl_val}<-{itemValue}'
                logStr = f'{stock_name},今日持仓盈亏,金额小于-{itemValue}（{today_pl_val}）'
            else:
                execStr = f'1==0'
                logStr = '策略选项异常，请检查'
        else:
            execStr = f'1==0'
            logStr = '策略选项异常，请检查'
        return execStr, logStr

    # 时间：正股：期权
    def STK_07(self, item, code, O_name, option, ifSummer, now_time, stock_name=''):
        if item['cItem'] == '开盘过去时间':
            itemValue = item['itemValue']
            hmd = itemValue.split(':')  # 转换为秒
            itemValue_sec = int(hmd[0]) * 3600 + int(hmd[1]) * 60 + int(hmd[2])
            today = str(now_time.date())
            preDay = str((now_time+datetime.timedelta(days=-1)).date())
            if 'US.' in code:
                if ifSummer:  # 夏令时
                    if 'pre' in option:  # 如果存在盘前，就是盘前，
                        openTime = f'{today} 16:00:00' if '16:00:00' <= str(
                            now_time.time()) <= '23:59:59' else f'{preDay} 16:00:00'
                    elif 'pre' not in option and 'middle' in option:  # 如果没有盘前，有盘中，就是盘中,
                        openTime = f'{today} 21:30:00' if '16:00:00' <= str(
                            now_time.time()) <= '23:59:59' else f'{preDay} 21:30:00'
                    elif 'pre' not in option and 'middle' not in option:  # 如果没有盘前盘中，就是盘后
                        # openTime = f'{getLastDay()} 04:00:00' if '16:00:00' <= str(
                        #     now_time.time()) <= '23:59:59' else f'{getPreDay()} 04:00:00'
                        return [False], '不支持单独的盘后交易 X.'
                    else:
                        return [False], '时段错误 X.'
                else:
                    if 'pre' in option:  # 如果存在盘前，就是盘前，
                        openTime = f'{today} 17:00:00' if '17:00:00' <= str(
                            now_time.time()) <= '23:59:59' else f'{preDay} 17:00:00'
                    elif 'pre' not in option and 'middle' in option:  # 如果没有盘前，有盘中，就是盘中,
                        openTime = f'{today} 22:30:00' if '17:00:00' <= str(
                            now_time.time()) <= '23:59:59' else f'{preDay} 22:30:00'
                    elif 'pre' not in option and 'middle' not in option:  # 如果没有盘前盘中，就是盘后
                        # openTime = f'{getLastDay()} 05:00:00' if '17:00:00' <= str(
                        #     now_time.time()) <= '23:59:59' else f'{getPreDay()} 05:00:00'
                        return [False], '不支持单独的盘后交易 X.'
                    else:
                        return [False], '时段错误 X.'
            else:  # 港股和A股
                openTime = f'{today} 09:30:00'

            openTime = datetime.datetime.strptime(openTime, '%Y-%m-%d %H:%M:%S')
            diff = (now_time - openTime).seconds

            execStr = f'{diff}>{itemValue_sec}'
            logStr = f'{stock_name},距离开盘过去{itemValue}（{str(now_time - openTime).split(".")[0]}）'
            if diff > itemValue_sec and '_配置项' in O_name:
                return [True], logStr + '√.(终止)'

        elif item['cItem'] == '指定时间':
            itemValue = item['itemValue']
            now = now_time.strftime("%Y-%m-%d %H:%M:%S")
            execStr = f"'{now}'>'{itemValue}'"
            logStr = f'{stock_name},具体时间大于{itemValue.split(" ")[-1]}（{now.split(" ")[-1]}）'
        else:
            execStr = f'1==0'
            logStr = '策略选项异常，请检查'
        return execStr, logStr

    # 市值：正股，个股对比
    def STK_08(self, item, market_val, stock_name=''):
        label = item['label_value'].replace(':', '')  # 单位
        itemValue = item['itemValue']
        market_val = round(market_val / 100000000, 2) if label == '亿' else round(market_val / 10000, 2)
        try:
            execStr = f'{market_val} {opt_transfor[item["bItem"]]} {itemValue}'
            logStr = f'{stock_name},当前市值{item["bItem"]}{itemValue}{label}（{market_val}){label}）'
        except:
            execStr = f'1==0'
            logStr = f'{item["aItem"]}策略选项异常，请检查'
        return execStr,logStr

    # 成交额变化：正股，个股对比
    def STK_09(self, item, code, turnover, option, ifSummer, bst,cur, now_time, r, stock_name=''):
        # 美股非期权的成交额获取
        if 'US.' in code and len(code) < 11 and self.ifTest==False:
            if r.hexists('usRealTurnover', code):
                turnover = float(r.hget('usRealTurnover', code))
            else:
                return [False], '成交额为0 X.'
        else:
            turnover = turnover

        label = item['label_value'].replace(':', '')  # 单位
        turnover = round(turnover / 100000000, 2) if label == '亿' else round(turnover / 10000, 2)
        if turnover == 0:
            return [False], '实时成交额为0'

        tbl_name = option[f'tbl_name_{bst}'][0]

        # 加载临时表该时刻的数据
        try:
            if 'US.' in code:
                # 美股要用当前时间
                if ifSummer:  # 夏令时
                    turnover_s_time = now_time + datetime.timedelta(hours=-12)
                else:
                    turnover_s_time = now_time + datetime.timedelta(hours=-13)
            else:
                turnover_s_time = now_time
            cur.execute(f'select turnover from {tbl_name} where time<="{str(turnover_s_time.time())[:8]}" ORDER BY time desc limit 1 ')
            sql_turnover = round(cur.fetchone()[0] / 100000000, 2) if label == '亿' else round(cur.fetchone()[0] / 10000, 2)  # 该时刻的成交额对比值
        except Exception as e:
            return [False], f'{item["aItem"]} {e} 数据准备中...'

        days = item['bItem']
        itemValue = item['itemValue']
        try:
            if item['cItem'] == '当前成交额对比N天累计成交额平均变化':  # 当前成交额对比N天累计成交额平均变化
                turnoverValue = round(turnover - sql_turnover,2)
                if item['dItem'] == '涨':
                    execStr = f'{turnoverValue}>{itemValue}'
                    logStr = f'{stock_name},当前成交额对比{days}天累计成交额平均变化 增加{itemValue}{label}({turnoverValue}{label})'
                elif item['dItem'] == '跌':
                    execStr = f'{turnoverValue}<-{itemValue}'
                    logStr = f'{stock_name},当前成交额对比{days}天累计成交额平均变化 減少{itemValue}{label}({turnoverValue}{label})'

            elif item['cItem'] == '当前成交额对比N天前的成交额 变化':  #
                turnoverValue = round(turnover - sql_turnover,2)
                if item['dItem'] == '涨':
                    execStr = f'{turnoverValue}>{itemValue}'
                    logStr = f'{stock_name},当前成交额对比{days}天前的成交额变化 增加{itemValue}{label}({turnoverValue}{label})'
                elif item['dItem'] == '跌':
                    execStr = f'{turnoverValue}<-{itemValue}'
                    logStr = f'{stock_name},当前成交额对比{days}天前的成交额变化 減少{itemValue}{label}({turnoverValue}{label})'

            elif item['cItem'] == '当前成交额对比N天内同周期成交额变化':
                turnoverValue = round(turnover - sql_turnover,2)
                if item['dItem'] == '涨':
                    execStr = f'{turnoverValue}>{itemValue}'
                    logStr = f'{stock_name},当前成交额对比{days}天内的当天均值的成交额变化 增加{itemValue}{label}({turnoverValue}{label})'
                elif item['dItem'] == '跌':
                    execStr = f'{turnoverValue}<-{itemValue}'
                    logStr = f'{stock_name},当前成交额对比{days}天内的当天均值的成交额变化 減少{itemValue}{label}({turnoverValue}{label})'

            elif item['cItem'] == '当前成交额对比N天成交额是否最高':  # 是否最高
                turnoverValue = sql_turnover
                execStr = f'turnover>{turnoverValue}'
                logStr = f'{stock_name},当前成交额在过去{days}天是否最高{turnover}{label}({turnoverValue}{label})'
            elif item['cItem'] == '当前成交额对比N天成交额是否最低':  # 当前成交额对比N天成交额是否最低
                turnoverValue = sql_turnover
                execStr = f'turnover<{turnoverValue}'
                logStr = f'{stock_name},当前成交额在过去{days}天是否最低{turnover}{label}({turnoverValue}{label})'
        except Exception as e:
            execStr = f'1==0'
            logStr = '策略选项异常，请检查'
        return execStr,logStr

    # 异动：正股，个股对比 [期权？]
    def STK_10(self, item, code, r):
        if item['bItem'] == '大盘异动':  # 均值
            k = {'HK':'HK.800000', 'US':'US.SPX', 'SZ':'SH.000001', 'SH':'SH.000001'}[code[:2]]
            k = f'{k}|{item["cItem"]}|{item["dItem"]}'  # redis的key
            status, indexExceptStr = eval(r.hget(f'StockExceptStatue{TrdEnv}', k))
            execStr = '1==1' if status == 1 else '1==0'
            logStr = indexExceptStr
        elif item['bItem'] == '个股异动':  #
            if len(code) > 10:
                return f'1==0', '期权暂不支持个股异动'
            # k = f'{code}|{item["cItem"]}|{item["dItem"]}'  # redis的key
            # status, indexExceptStr = eval(r.hget(f'StockExceptStatue{TrdEnv}', k))
            # execStr = '1==1' if status == 1 else '1==0'
            # logStr = indexExceptStr
            execStr = f'1==0'
            logStr = '个股异动程序为启动'
        else:
            execStr = f'1==0'
            logStr = '策略选项异常，请检查'
        return execStr,logStr

    # 成交额对比：个股对比
    def STK_11(self, item, mainCode,compCode,mainT,compT, r, code_name):
        # 美股非期权的成交额获取
        if 'US.' in mainCode and self.ifTest==False:
            if r.hexists('usRealTurnover', mainCode):
                mainT = float(r.hget('usRealTurnover', mainCode))
            else:
                return [False], '成交额为0 X.'
        else:
            mainT = mainT


        if 'US.' in compCode and self.ifTest==False:
            if r.hexists('usRealTurnover', compCode):
                compT = float(r.hget('usRealTurnover', compCode))
            else:
                return [False], '成交额为0 X.'
        else:
            compT = compT

        label = item['label_value'].replace(':', '')  # 单位
        itemValue = item['itemValue']
        dev_value = 100000000 if label == '亿' else 10000  # 除数
        mainT = round(float(mainT) / dev_value, 2)
        compT = round(float(compT) / dev_value, 2)
        if item['bItem'] == '额度':
            execStr = f'{mainT}-{compT} {opt_transfor[item["cItem"]]} {itemValue}'
            logStr = f'{code_name[mainCode]}成交额({mainT}{label}) 对比{code_name[compCode]}成交额({compT}{label}){item["cItem"]}{itemValue}{label} ({round(mainT - compT, 2)}{label})'
        elif item['bItem'] == '幅度':
            execStr = f'({mainT}-{compT})/{compT}*100 {opt_transfor[item["cItem"]]} {itemValue}'
            logStr = f'{code_name[mainCode]}成交额({mainT}{label}) 对比{code_name[compCode]}成交额({compT}{label}){item["cItem"]}{itemValue}% ({round((mainT - compT) / compT * 100, 2)})'
        else:
            execStr = f'1==0'
            logStr = '策略选项异常，请检查'
        return execStr,logStr

    # 1.个股连涨/跌x天: 正股，个股对比
    def STK_new_01(self, item, option, bst,UDP):
        itemValue = item['itemValue']
        if item['cItem'] == '包括当天':
            if option[f'个股连涨/跌x天{bst}'] == [True]:  # 在前n-1天成立的情况下
                if item['bItem'] == '个股连涨' and UDP > 0:
                    execStr = f'1==1'
                    logStr = f"{item['bItem']}{int(itemValue)}天({item['cItem']}) 成立"
                elif item['bItem'] == '个股连跌' and UDP < 0:
                    execStr = f'1==1'
                    logStr = f"{item['bItem']}{int(itemValue)}天({item['cItem']}) 成立"
                else:
                    execStr = f'1==0'
                    logStr = f"{item['bItem']}{int(itemValue)}天({item['cItem']}) 不成立"
            else:
                execStr = f'1==0'
                logStr = f"{item['bItem']}{int(itemValue)}天({item['cItem']}) 不成立"

        else:  # 不包括当天
            if option[f'个股连涨/跌x天{bst}'] == [True]:
                execStr = f'1==1'
                logStr = f"{item['bItem']}{int(itemValue)}天({item['cItem']}) 成立"
            else:
                execStr = f'1==0'
                logStr = f"{item['bItem']}{int(itemValue)}天({item['cItem']}) 不成立"
        return execStr,logStr

    # 2.个股涨%后跌%: 正股，个股对比
    def STK_new_02(self, item, option, UDP, r):
        first_v = item['cItem']  # 前面的值
        second_v = item['itemValue']  # 后面的值
        if not r.hexists('s_add_2', option['o_name'][0]):  # 如果为空，则首次存入, 方向要一致
            if (float(first_v) > 0 and UDP > 0) or (-float(first_v) < 0 and UDP < 0):
                # 如果当前已经满足第一步，就直接进入第二步
                if item['bItem'] == '涨' and UDP > 0 and UDP > float(first_v):
                    r.hset('s_add_2', option['o_name'][0],
                           str([UDP, True, False]))  # 第一个false是第一步是否成立的标志，第二个false为是否过了0点的标志
                    logStr = f'先涨{first_v}%({UDP}%) 达成'
                elif item['bItem'] == '跌' and UDP < 0 and UDP < -float(first_v):
                    r.hset('s_add_2', option['o_name'][0],
                           str([UDP, True, False]))  # 第一个false是第一步是否成立的标志，第二个false为是否过了0点的标志
                    logStr = f'先跌{first_v}%({UDP}%) 达成'
                else:  # 没有满足第一步
                    r.hset('s_add_2', option['o_name'][0],
                           str([UDP, False, False]))  # 第一个false是第一步是否成立的标志，第二个false为是否过了0点的标志
                    logStr = f"先{item['bItem']}{first_v}%({UDP}%) 不成立"
            else:  # 如果方向不一致，则跳过当前
                logStr = f"先{item['bItem']}的方向不一致, {first_v}%({UDP}%)"
            execStr = f'1==0'
        else:  # 第二条数据的话，先获取缓存数值
            res = eval(r.hget('s_add_2', option['o_name'][0]))
            # 判断是处于第几步
            if res[1] == False:  # 处于第一步， 判断是否能进入第二步(满足涨了x%)
                if item['bItem'] == '涨' and UDP > 0 and UDP > float(first_v):
                    res[1] = True  #
                    res[0] = UDP
                    logStr = f'先涨{first_v}%({UDP}%) 达成'
                elif item['bItem'] == '跌' and UDP < 0 and UDP < -float(first_v):
                    res[1] = True  #
                    res[0] = UDP
                    logStr = f'先跌{first_v}%({UDP}%) 达成'
                else:
                    logStr = f"先{item['bItem']}{first_v}%({UDP}%) 不成立"
                execStr = f'1==0'
                r.hset('s_add_2', option['o_name'][0], str(res))  # 重新更新到redis
            elif res[1] == True:  # 处于第二步，判断最终是否成立
                if item['dItem'] == '跌' and UDP < -float(second_v):  # 先涨1 ，再跌5
                    logStr = f"先{item['bItem']}{first_v}%({res[0]}%)成立，后{item['dItem']}{second_v}%({UDP}%) 成立"
                    execStr = f'1==1'
                elif item['dItem'] == '涨' and UDP > float(second_v):  # 先跌5，再涨1
                    logStr = f"先{item['bItem']}{first_v}%({res[0]}%)成立，后{item['dItem']}{second_v}%({UDP}%) 成立"
                    execStr = f'1==1'
                else:
                    logStr = f"先{item['bItem']}{first_v}%({res[0]}%)成立，后{item['dItem']}{second_v}%({UDP}%) 不成立"
                    execStr = f'1==0'
            else:
                execStr = f'1==0'
                logStr = '策略选项异常，请检查'
        return execStr, logStr

    # 3.电商股上涨比例%：正股
    def STK_new_03(self, item, r, cache_data):
        itemValue = float(item['itemValue'])  # 后面的值
        codeList = r.hget('stock_code_class', item['bItem'])
        codeList = [x.split('   ')[0] for x in codeList.split(',')]
        if not all([True if x in cache_data else False for x in codeList]):
            return [False],'数据准备中'

        percent = [cache_data[x]['change_rate'] for x in codeList if 'change_rate' in cache_data[x]]

        if len(codeList) == len(percent):  # 刚开始的数据不足的情况
            if item['cItem'] == '上涨':
                up_percent = [x for x in percent if x > 0]  # 大于0的个数
                up_percent = len(up_percent) / len(percent) * 100
                if up_percent >= itemValue:
                    logStr = f"{item['bItem']}[类别] 上涨比例{itemValue}% ({up_percent}%)"
                    execStr = f'1==1'
                else:
                    logStr = f"{item['bItem']}[类别] 上涨比例{itemValue}% ({up_percent}%)"
                    execStr = f'1==0'
            elif item['cItem'] == '下跌':
                down_percent = [x for x in percent if x < 0]  # 大于0的个数
                down_percent = len(down_percent) / len(percent) * 100
                if down_percent >= itemValue:
                    logStr = f"{item['bItem']}[类别] 下跌比例{itemValue}% ({down_percent}%)"
                    execStr = f'1==1'
                else:
                    logStr = f"{item['bItem']}[类别] 下跌比例{itemValue}% ({down_percent}%)"
                    execStr = f'1==0'
            else:
                execStr = f'1==0'
                logStr = '策略选项异常，请检查'
        else:
            logStr = f"{item['bItem']}[类别] 数据准备中"
            execStr = f'1==0'
        return execStr,logStr

    # 4.大盘指数涨/跌X%后跌/涨X%：正股
    def STK_new_04(self, item, option, r, code, ifSummer, now_Time):
        ifing = True  # 是否继续判断
        # 盘前盘后，指数返回的False
        if 'US.' in code:
            if ifSummer:  # 夏令时
                if '16:00:00' <= str(now_Time.time())[:8] <= '21:30:00':  # 如果是夏令时盘前
                    execStr = f'1==0'
                    logStr = '处于夏令时盘前，美股指数未更新'
                    ifing = False
                elif '04:00:00' <= str(now_Time.time())[:8] <= '08:00:00':  # 如果是夏令时盘后
                    execStr = f'1==0'
                    logStr = '处于夏令时盘后，美股指数未更新'
                    ifing = False
            else:
                if '17:00:00' <= str(now_Time.time())[:8] <= '22:30:00':  # 如果是冬令时盘前
                    execStr = f'1==0'
                    logStr = '处于冬令时盘前，美股指数未更新'
                    ifing = False
                elif '05:00:00' <= str(now_Time.time())[:8] <= '09:00:00':  # 如果是冬令时盘后
                    execStr = f'1==0'
                    logStr = '处于冬令时盘后，美股指数未更新'
                    ifing = False
            if ifing == False:
                return [False], logStr

        a = item['cItem']
        b = item['itemValue']

        indexCode = {'US': 'US.SPX', 'HK': 'HK.800000', 'SZ': 'SH.000001', 'SH': 'SH.000001'}[
            option['code'][0][:2]]
        indexName = {'US.SPX': '标普500', 'HK.800000': '恒生指数', 'SH.000001': '上证指数'}[indexCode]
        udp = float(eval(r.hget('indexFutures', indexCode))['pcp'][:-1])
        if not r.hexists('s_add_4', option['o_name'][0]):  # 如果为空，则首次存入, 方向要一致
            if (float(a) > 0 and udp > 0) or (-float(a) < 0 and udp < 0):
                # 如果当前已经满足第一步，就直接进入第二步
                if item['bItem'] == '涨' and udp > 0 and udp > float(a):
                    r.hset('s_add_4', option['o_name'][0],
                           str([udp, True, False]))  # 第一个false是第一步是否成立的标志，第二个false为是否过了0点的标志
                    logStr = f'{indexName}先涨{a}%({udp}%) 达成'
                elif item['bItem'] == '跌' and udp < 0 and udp < -float(a):
                    r.hset('s_add_4', option['o_name'][0],
                           str([udp, True, False]))  # 第一个false是第一步是否成立的标志，第二个false为是否过了0点的标志
                    logStr = f'{indexName}先跌{a}%({udp}%) 达成'
                else:  # 没有满足第一步
                    r.hset('s_add_4', option['o_name'][0],
                           str([udp, False, False]))  # 第一个false是第一步是否成立的标志，第二个false为是否过了0点的标志
                    logStr = f"{indexName}先{item['bItem']}{a}%({udp}%) 不成立"
            else:  # 如果方向不一致，则跳过当前
                logStr = f"{indexName}先{item['bItem']}的方向不一致, {a}%({udp}%)"
            execStr = f'1==0'
        else:  # 第二条数据的话，先获取缓存数值
            res = eval(r.hget('s_add_4', option['o_name'][0]))
            # 如果zero==True的情况下，当前涨跌幅和第一步的方向一致则重置
            # 判断是处于第几步
            if res[1] == False:  # 处于第一步， 判断是否能进入第二步(满足涨了x%)
                if item['bItem'] == '涨' and udp > 0 and udp > float(a):
                    res[1] = True  #
                    res[0] = udp
                    logStr = f'{indexName}先涨{a}%({udp}%) 达成'
                elif item['bItem'] == '跌' and udp < 0 and udp < -float(a):
                    res[1] = True  #
                    res[0] = udp
                    logStr = f'{indexName}先跌{a}%({udp}%) 达成'
                else:
                    logStr = f"{indexName}先{item['bItem']}{a}%({udp}%) 不成立"
                execStr = f'1==0'
                r.hset('s_add_4', option['o_name'][0], str(res))  # 重新更新到redis
            elif res[1] == True:  # 处于第二步，判断最终是否成立d
                if item['dItem'] == '跌' and udp < -float(b):  # 先涨1 ，再跌5
                    logStr = f"{indexName}先{item['bItem']}{a}%({res[0]}%)成立，后{item['dItem']}{b}%({udp}%) 成立"
                    execStr = f'1==1'
                elif item['dItem'] == '涨' and udp > float(b):  # 先跌5，再涨1
                    logStr = f"{indexName}先{item['bItem']}{a}%({res[0]}%)成立，后{item['dItem']}{b}%({udp}%) 成立"
                    execStr = f'1==1'
                else:
                    logStr = f"{indexName}先{item['bItem']}{a}%({res[0]}%)成立，后{item['dItem']}{b}%({udp}%) 不成立"
                    execStr = f'1==0'
        return execStr, logStr

    # 6.历史最大/最高: 正股，个股对比
    def STK_new_06(self, item, option, bst, data):
        o = option[f'历史最大/最高{bst}'][0]
        if item['bItem'] == '历史当天最大涨幅':
            if data['change_rate'] > o:
                logStr = f"历史当天最大涨幅{o}%({data['change_rate']}%) 成立"
                execStr = f'1==1'
            else:
                logStr= f"历史当天最大涨幅{o}%({data['change_rate']}%) 不成立"
                execStr = f'1==0'
        elif item['bItem'] == '历史当天最大跌幅':
            if data['change_rate'] < o:
                logStr = f"历史当天最大跌幅{o}%({data['change_rate']}%) 成立"
                execStr = f'1==1'
            else:
                logStr = f"历史当天最大跌幅{o}%({data['change_rate']}%) 不成立"
                execStr = f'1==0'
        elif item['bItem'] == '历史当天最高价格':
            if data['last_price'] > o:
                logStr = f"历史当天最高价格{o}({data['last_price']}) 成立"
                execStr = f'1==1'
            else:
                logStr = f"历史当天最高价格{o}({data['last_price']}) 不成立"
                execStr = f'1==0'
        elif item['bItem'] == '历史当天最低价格':
            if data['last_price'] < o:
                logStr = f"历史当天最低价格{o}({data['last_price']}) 成立"
                execStr = f'1==1'
            else:
                logStr = f"历史当天最低价格{o}({data['last_price']}) 不成立"
                execStr = f'1==0'
        elif item['bItem'] == '历史收盘最大涨幅':
            if data['change_rate'] > o:
                logStr = f"历史收盘最大涨幅{o}({data['change_rate']}) 成立"
                execStr = f'1==1'
            else:
                logStr = f"历史收盘最大涨幅{o}({data['change_rate']}) 不成立"
                execStr = f'1==0'
        elif item['bItem'] == '历史收盘最大跌幅':
            if data['change_rate'] < o:
                logStr = f"历史收盘最大跌幅{o}({data['change_rate']}) 成立"
                execStr = f'1==1'
            else:
                logStr = f"历史收盘最大跌幅{o}({data['change_rate']}) 不成立"
                execStr = f'1==0'
        else:
            execStr = f'1==0'
            logStr = '策略选项异常，请检查'
        return execStr,logStr

    # 7.X天内涨/跌幅超过XX%: 正股，个股对比
    def STK_new_07(self, item,option, bst,data):
        if item['dItem'] == '不包括当天':
            if option[f'X天内涨/跌幅超过XX%{bst}'] == [True]:
                logStr = f"{item['bItem']}内(不包括当天) {item['cItem']}超过{item['itemValue']}% 成立"
                execStr = f'1==1'
            else:
                logStr = f"{item['bItem']}内(不包括当天) {item['cItem']}超过{item['itemValue']}% 不成立"
                execStr = f'1==0'
        else:
            o = option[f'X天内涨/跌幅超过XX%{bst}'][0][0]  # x天前的开盘价
            o_udp = round((data['last_price'] - o) / o * 100, 2)  # 最新价对比n天前的开盘价，幅度变化了多少

            a = item['bItem']
            b = item['itemValue']
            if item['cItem'] == '涨幅' and o_udp > float(b):
                logStr = f"{a}天(包括当天)前开盘价{o} {item['cItem']}超过{b}% ({o_udp}%) 成立"
                execStr = f'1==1'
            elif item['cItem'] == '跌幅' and o_udp < -float(b):
                logStr = f"{a}天(包括当天)前开盘价{o} {item['cItem']}超过{b}% ({o_udp}%) 成立"
                execStr = f'1==1'
            else:
                logStr = f"{a}天(包括当天)前开盘价{o} {item['cItem']}超过{b}% ({o_udp}%) 不成立"
                execStr = f'1==0'
        return execStr, logStr

    # 8.个股中历史涨/跌幅排名X: 正股，个股对比
    def STK_new_08(self, item, option, bst, data):
        itemValue = item['itemValue']
        o = option[f'个股中历史涨/跌幅排名X{bst}'][0]
        if item['bItem'] == '收盘涨幅' and data['change_rate'] > o:
            logStr = f"收盘涨幅排名{int(itemValue)}的幅度{o}% ({data['change_rate']}%) 成立"
            execStr = f'1==1'
        elif item['bItem'] == '收盘跌幅' and data['change_rate'] < o:
            logStr = f"收盘跌幅排名{int(itemValue)}的幅度{o}% ({data['change_rate']}%) 成立"
            execStr = f'1==1'
        elif item['bItem'] == '最大涨幅' and data['change_rate'] > o:
            logStr = f"最大涨幅排名{int(itemValue)}的幅度{o}% ({data['change_rate']}%) 成立"
            execStr = f'1==1'
        elif item['bItem'] == '最大跌幅' and data['change_rate'] < o:
            logStr = f"最大跌幅排名{int(itemValue)}的幅度{o}% ({data['change_rate']}%) 成立"
            execStr = f'1==1'
        else:
            logStr = f"历史{item['bItem']}排名{int(itemValue)}的幅度{o}% ({data['change_rate']}%) 不成立"
            execStr = f'1==0'
        return execStr, logStr

    # 9.个股中达到历史最大涨/跌幅的XX%: 正股，个股对比
    def STK_new_09(self, item, option, bst, data):
        itemValue = item['itemValue']
        o = option[f'个股中达到历史最大涨/跌幅的XX%{bst}'][0]
        if item['bItem'] == '最大涨幅' and data['change_rate'] > o:
            logStr = f"历史最大涨幅的{itemValue}%为{o}% ({data['change_rate']}%) 成立"
            execStr = f'1==1'
        elif item['bItem'] == '最大跌幅' and data['change_rate'] < o:
            logStr = f"历史最大跌幅的{itemValue}%为{o}% ({data['change_rate']}%) 成立"
            execStr = f'1==1'
        else:
            execStr = f'1==0'
            logStr = f"历史{item['bItem']}的{itemValue}%为{o}% ({data['change_rate']}%) 不成立"
        return execStr, logStr

    # 10.XX类股票跌同时XX类股票涨: 正股
    def STK_new_10(self, item, cache_data, code_name, r):
        one_codeList = r.hget('stock_code_class', item['bItem'])
        one_codeList = [x.split('   ')[0] for x in one_codeList.split(',')]
        one_percent = [cache_data[x]['change_rate'] for x in one_codeList if
                       x in cache_data and 'change_rate' in cache_data[x]]

        two_codeList = r.hget('stock_code_class', item['dItem'])
        two_codeList = [x.split('   ')[0] for x in two_codeList.split(',')]
        two_percent = [cache_data[x]['change_rate'] for x in two_codeList if
                       x in cache_data and 'change_rate' in cache_data[x]]
        if len(one_codeList) != len(one_percent) or len(two_codeList) != len(two_percent):  # 刚开始的数据不足的情况
            logStr = f"{item['bItem']} 和 {item['dItem']} [类别] 数据准备中"
            execStr = f'1==0'
        else:
            str1 = [f"{code_name[x]}{cache_data[x]['change_rate']}%" for x in one_codeList]
            str2 = [f"{code_name[x]}{cache_data[x]['change_rate']}%" for x in two_codeList]
            if item['cItem'] == '全部涨' and item['eItem'] == '全部跌':
                a = [True if x > 0 else False for x in one_percent]
                b = [True if x < 0 else False for x in two_percent]
                if all(a) and all(b):
                    logStr = f"[{item['bItem']}]{item['cItem']} 同时 [{item['dItem']}]{item['eItem']} 成立</br>{str1}</br>{str2}"
                    execStr = f'1==1'
                else:
                    logStr = f"[{item['bItem']}]{item['cItem']} 同时 [{item['dItem']}]{item['eItem']} 不成立</br>{str1}</br>{str2}"
                    execStr = f'1==0'
            elif item['cItem'] == '全部跌' and item['eItem'] == '全部涨':
                a = [True if x < 0 else False for x in one_percent]
                b = [True if x > 0 else False for x in two_percent]
                if all(a) and all(b):
                    logStr = f"[{item['bItem']}]{item['cItem']} 同时 [{item['dItem']}]{item['eItem']} 成立</br>{str1}</br>{str2}"
                    execStr = f'1==1'
                else:
                    logStr = f"[{item['bItem']}]{item['cItem']} 同时 [{item['dItem']}]{item['eItem']} 不成立</br>{str1}</br>{str2}"
                    execStr = f'1==0'
            else:
                logStr = f"策略选项相同"
                execStr = f'1==0'
        return execStr, logStr

    # 11.XX个股涨/跌同时XX个股跌/涨: 正股
    def STK_new_11(self, item, cache_data):
        name1, code1 = item['bItem'].split(',')
        name2, code2 = item['dItem'].split(',')
        if code1 in cache_data and code2 in cache_data and 'change_rate' in cache_data[
            code1] and 'change_rate' in \
                cache_data[code2]:
            if item['cItem'] == '涨' and item['eItem'] == '跌':
                if cache_data[code1]['change_rate'] > 0 and cache_data[code2]['change_rate'] < 0:
                    logStr = f"[{name1}]涨({cache_data[code1]['change_rate']}%)的同时[{name2}]跌({cache_data[code2]['change_rate']}%) 成立"
                    execStr = f'1==1'
                else:
                    logStr = f"[{name1}]涨({cache_data[code1]['change_rate']}%)的同时[{name2}]跌({cache_data[code2]['change_rate']}%) 不成立"
                    execStr = f'1==0'
            elif item['cItem'] == '跌' and item['eItem'] == '涨':
                if cache_data[code1]['change_rate'] < 0 and cache_data[code2]['change_rate'] > 0:
                    logStr = f"[{name1}]跌({cache_data[code1]['change_rate']}%)的同时[{name2}]涨({cache_data[code2]['change_rate']}%) 成立"
                    execStr = f'1==1'
                else:
                    logStr = f"[{name1}]跌({cache_data[code1]['change_rate']}%)的同时[{name2}]涨({cache_data[code2]['change_rate']}%) 不成立"
                    execStr = f'1==0'
            else:
                logStr = f"涨跌选项相同"
                execStr = f'1==0'
        else:
            logStr = f"{item['aItem']} 数据准备中"
            execStr = f'1==0'
        return execStr, logStr

    # 12.XX秒跌幅XX%，XX秒涨幅XX%: 正股，个股对比
    def STK_new_12(self, item, option, now_Time, data, r):
        # 累计30秒的数据，当前涨跌幅和30秒前的差距，第一条不足30秒 跳过继续积累
        # print([Time, data['change_rate']])
        if not r.hexists('s_add_12', option['o_name'][0]):
            r.hset('s_add_12', option['o_name'][0], str([[now_Time, data['change_rate']]]))
            return [False], f"不足{item['bItem']}秒"
        else:
            dataList = eval(r.hget('s_add_12', option['o_name'][0]))
            first = [x for x in dataList if (now_Time - x[0]).seconds >= int(item['bItem'])]  # 所有大于30秒
            if first != []:
                udp_diff = round(data['change_rate'] - first[-1][1], 2)  # 最新那条
                if item['cItem'] == '涨':
                    if udp_diff >= float(item['itemValue']):
                        logStr = f"{item['bItem']}秒{item['cItem']}幅{item['itemValue']}% ({udp_diff}%) 当前幅度:{data['change_rate']} 对比值:({str(first[-1][0])[10:19]},{first[-1][1]})成立"
                        execStr = f'1==1'
                    else:
                        logStr = f"{item['bItem']}秒{item['cItem']}幅{item['itemValue']}% ({udp_diff}%) 当前幅度:{data['change_rate']} 对比值:({str(first[-1][0])[10:19]},{first[-1][1]})不成立"
                        execStr = f'1==0'
                elif item['cItem'] == '跌':
                    if abs(udp_diff) >= float(item['itemValue']):
                        logStr = f"{item['bItem']}秒{item['cItem']}幅{item['itemValue']}% ({udp_diff}%) 当前幅度:{data['change_rate']} 对比值:({str(first[-1][0])[10:19]},{first[-1][1]})成立"
                        execStr = f'1==1'
                    else:
                        logStr = f"{item['bItem']}秒{item['cItem']}幅{item['itemValue']}% ({udp_diff}%) 当前幅度:{data['change_rate']} 对比值:({str(first[-1][0])[10:19]},{first[-1][1]})不成立"
                        execStr = f'1==0'
                else:
                    execStr = f'1==0'
                    logStr = '策略选项异常，请检查'
                if str(dataList[-1][0])[:19] == str(now_Time)[:19]:  # 如果时间一样则替换涨跌幅
                    dataList[-1][1] = data['change_rate']
                else:  # w如果时间不一样 加到末尾
                    dataList.append([now_Time, data['change_rate']])
                dataList = dataList[-int(item['bItem']) - 10:]  # 30秒保留最新的30条
                r.hset('s_add_12', option['o_name'][0], str(dataList))
            else:
                if str(dataList[-1][0])[:19] == str(now_Time)[:19]:  # 如果时间一样则替换涨跌幅
                    dataList[-1][1] = data['change_rate']
                else:  # w如果时间不一样 加到末尾
                    dataList.append([now_Time, data['change_rate']])
                dataList = dataList[-int(item['bItem']) - 10:]  # 30秒保留最新的30条
                r.hset('s_add_12', option['o_name'][0], str(dataList))
                return [False], f"不足{item['bItem']}秒"
        return execStr, logStr

    # 13.周期交易日: 正股
    def STK_new_13(self, item, code, ifSummer, now_Time):
        weekDict = {'周一': 0, '周二': 1, '周三': 2, '周四': 3, '周五': 4}
        weekDict_trans = {0: '周一', 1: '周二', 2: '周三', 3: '周四', 4: '周五'}
        weekList = [weekDict[x] for x in item['itemValue'].split(',')]
        if 'US.' in code:
            if ifSummer:
                T = now_Time + datetime.timedelta(hours=-12)
            else:
                T = now_Time + datetime.timedelta(hours=-13)
        else:
            T = now_Time

        if T.weekday() in weekList:  # 如果在周期交易日里面则
            logStr = f"当天{weekDict_trans[T.weekday()]} 在【{item['itemValue']}】中"
            execStr = f'1==1'
        else:
            return [False], f"当天{weekDict_trans[T.weekday()]} 不在 【{item['itemValue']}】中 X."
        return execStr, logStr

    # 1.指数涨跌
    def IDX_01(self, item, ifSummer, now_Time, idx_data, idx_code_name):
        idx_name, idx_code = idx_code_name.split('   ')
        ifing = True  # 是否继续判断
        # 盘前盘后，指数返回的False
        if 'US.' in idx_code:
            if ifSummer:  # 夏令时
                if '16:00:00' <= str(now_Time.time())[:8] <= '21:30:00':  # 如果是夏令时盘前
                    execStr = f'1==0'
                    logStr = '处于夏令时盘前，美股指数未更新'
                    ifing = False
                elif '04:00:00' <= str(now_Time.time())[:8] <= '08:00:00':  # 如果是夏令时盘后
                    execStr = f'1==0'
                    logStr = '处于夏令时盘后，美股指数未更新'
                    ifing = False
            else:
                if '17:00:00' <= str(now_Time.time())[:8] <= '22:30:00':  # 如果是冬令时盘前
                    execStr = f'1==0'
                    logStr = '处于冬令时盘前，美股指数未更新'
                    ifing = False
                elif '05:00:00' <= str(now_Time.time())[:8] <= '09:00:00':  # 如果是冬令时盘后
                    execStr = f'1==0'
                    logStr = '处于冬令时盘后，美股指数未更新'
                    ifing = False

        if ifing:
            itemValue = item['itemValue']
            # 获取实时指数数据, 根据股票代码划分对应的指数
            index_price = float(idx_data['close'])
            index_UDP = float(idx_data['udp'])

            if item['bItem'] == '固定值':  # 价格
                execStr = f'{index_price} {opt_transfor[item["cItem"]]} {itemValue}'
                logStr = f'{idx_name}固定值{item["cItem"]}{itemValue}（{index_price}）'
            elif item['bItem'] == '涨跌幅':  # 涨跌幅
                if item['cItem'] == '涨':
                    execStr = f'{index_UDP}>{itemValue}'
                    logStr = f'{idx_name}涨跌幅涨{itemValue}%（{index_UDP}%）'
                elif item['cItem'] == '跌':
                    execStr = f'{index_UDP}<-{itemValue}'
                    logStr = f'{idx_name}涨跌幅跌-{itemValue}%（{index_UDP}%）'
                else:
                    execStr = f'1==0'
                    logStr = '策略选项异常，请检查'
            else:
                execStr = f'1==0'
                logStr = '策略选项异常，请检查'
            return execStr, logStr
        else:
            return execStr, logStr

    # 2.指数连涨/跌x天
    def IDX_02(self, item, option, bst, idx_data,idx_code_name):
        idx_name, idx_code = idx_code_name.split('   ')
        itemValue = item['itemValue']
        UDP = idx_data['udp']
        if item['cItem'] == '包括当天':
            if option[f'{item["aItem"]}{bst}'] == [True]:  # 在前n-1天成立的情况下
                if item['bItem'] == '指数连涨' and UDP > 0:
                    logStr = f"{item['bItem']}({idx_name}){int(itemValue)}天({item['cItem']})({UDP}%) 成立"
                    execStr = f'1==1'
                elif item['bItem'] == '指数连跌' and UDP < 0:
                    logStr = f"{item['bItem']}({idx_name}){int(itemValue)}天({item['cItem']})({UDP}%) 成立"
                    execStr = f'1==1'
                else:
                    logStr = f"{item['bItem']}({idx_name}){int(itemValue)}天({item['cItem']})({UDP}%) 不成立"
                    execStr = f'1==0'
            else:
                logStr = f"{item['bItem']}({idx_name}){int(itemValue)}天({item['cItem']})({UDP}%) 不成立"
                execStr = f'1==0'

        else:  # 不包括当天
            if option[f'{item["aItem"]}{bst}'] == [True]:
                logStr = f"{item['bItem']}({idx_name}){int(itemValue)}天({item['cItem']})({UDP}%) 成立"
                execStr = f'1==1'
            else:
                logStr = f"{item['bItem']}({idx_name}){int(itemValue)}天({item['cItem']})({UDP}%) 不成立"
                execStr = f'1==0'
        return execStr, logStr

    # 3.指数涨1 跌5
    def IDX_03(self, item, option, idx_data, idx_code_name,r):
        a = item['cItem']
        b = item['itemValue']
        idx_name, idx_code = idx_code_name.split('   ')

        udp = idx_data['udp']
        if not r.hexists('s_add_2IDX', option['o_name'][0]):  # 如果为空，则首次存入, 方向要一致
            if (float(a) > 0 and udp > 0) or (-float(a) < 0 and udp < 0):
                # 如果当前已经满足第一步，就直接进入第二步
                if item['bItem'] == '涨' and udp > 0 and udp > float(a):
                    r.hset('s_add_2IDX', option['o_name'][0],
                           str([udp, True, False]))  # 第一个false是第一步是否成立的标志，第二个false为是否过了0点的标志
                    logStr = f'({idx_name})先涨{a}%({udp}%) 达成'
                elif item['bItem'] == '跌' and udp < 0 and udp < -float(a):
                    r.hset('s_add_2IDX', option['o_name'][0],
                           str([udp, True, False]))  # 第一个false是第一步是否成立的标志，第二个false为是否过了0点的标志
                    logStr = f'({idx_name})先跌{a}%({udp}%) 达成'
                else:  # 没有满足第一步
                    r.hset('s_add_2IDX', option['o_name'][0],
                           str([udp, False, False]))  # 第一个false是第一步是否成立的标志，第二个false为是否过了0点的标志
                    logStr = f"({idx_name})先{item['bItem']}{a}%({udp}%) 不成立"
            else:  # 如果方向不一致，则跳过当前
                logStr = f"({idx_name})先{item['bItem']}的方向不一致, {a}%({udp}%)"
            execStr = f'1==0'
        else:  # 第二条数据的话，先获取缓存数值
            res = eval(r.hget('s_add_2IDX', option['o_name'][0]))
            # 判断是处于第几步
            if res[1] == False:  # 处于第一步， 判断是否能进入第二步(满足涨了x%)
                if item['bItem'] == '涨' and udp > 0 and udp > float(a):
                    res[1] = True  #
                    res[0] = udp
                    logStr = f'({idx_name})先涨{a}%({udp}%) 达成'
                elif item['bItem'] == '跌' and udp < 0 and udp < -float(a):
                    res[1] = True  #
                    res[0] = udp
                    logStr = f'({idx_name})先跌{a}%({udp}%) 达成'
                else:
                    logStr = f"({idx_name})先{item['bItem']}{a}%({udp}%) 不成立"
                execStr = f'1==0'
                r.hset('s_add_2IDX', option['o_name'][0], str(res))  # 重新更新到redis
            elif res[1] == True:  # 处于第二步，判断最终是否成立
                if item['dItem'] == '跌' and udp < -float(b):  # 先涨1 ，再跌5
                    logStr = f"({idx_name})先{item['bItem']}{a}%({res[0]}%)成立，后{item['dItem']}{b}%({udp}%) 成立"
                    execStr = f'1==1'
                elif item['dItem'] == '涨' and udp > float(b):  # 先跌5，再涨1
                    logStr = f"({idx_name})先{item['bItem']}{a}%({res[0]}%)成立，后{item['dItem']}{b}%({udp}%) 成立"
                    execStr = f'1==1'
                else:
                    logStr = f"({idx_name})先{item['bItem']}{a}%({res[0]}%)成立，后{item['dItem']}{b}%({udp}%) 不成立"
                    execStr = f'1==0'
            else:
                execStr = f'1==0'
                logStr = '策略选项异常，请检查'
        return execStr, logStr

    # 4.历史最大/最高
    def IDX_04(self, item, option, bst, idx_data, idx_code_name):
        idx_name, idx_code = idx_code_name.split('   ')
        o = option[f'{item["aItem"]}{bst}'][0]
        if item['bItem'] == '历史当天最大涨幅':
            yes_or_no = True if idx_data['udp'] > o else False
            logStr = f"({idx_name})历史当天最大涨幅{o}%({idx_data['udp']}%) {'成立' if yes_or_no else '不成立'}"
            execStr = f'1==1' if yes_or_no else f'1==0'
        elif item['bItem'] == '历史当天最大跌幅':
            yes_or_no = True if idx_data['udp'] < o else False
            logStr = f"({idx_name})历史当天最大跌幅{o}%({idx_data['udp']}%) {'成立' if yes_or_no else '不成立'}"
            execStr = f'1==1' if yes_or_no else f'1==0'
        elif item['bItem'] == '历史当天最高价格':
            yes_or_no = True if idx_data['close'] > o else False
            logStr = f"({idx_name})历史当天最高价格{o}({idx_data['close']}) {'成立' if yes_or_no else '不成立'}"
            execStr = f'1==1' if yes_or_no else f'1==0'
        elif item['bItem'] == '历史当天最低价格':
            yes_or_no = True if idx_data['close'] < o else False
            logStr = f"({idx_name})历史当天最低价格{o}({idx_data['close']}) {'成立' if yes_or_no else '不成立'}"
            execStr = f'1==1' if yes_or_no else f'1==0'
        elif item['bItem'] == '历史收盘最大涨幅':
            yes_or_no = True if idx_data['udp'] > o else False
            logStr = f"({idx_name})历史收盘最大涨幅{o}({idx_data['udp']}) {'成立' if yes_or_no else '不成立'}"
            execStr = f'1==1' if yes_or_no else f'1==0'
        elif item['bItem'] == '历史收盘最大跌幅':
            yes_or_no = True if idx_data['udp'] < o else False
            logStr = f"({idx_name})历史收盘最大跌幅{o}({idx_data['udp']}) {'成立' if yes_or_no else '不成立'}"
            execStr = f'1==1' if yes_or_no else f'1==0'
        else:
            execStr = f'1==0'
            logStr = '策略选项异常，请检查'
        return execStr, logStr

    # 5.X天内涨/跌幅超过XX%
    def IDX_05(self, item, option, bst, idx_data, idx_code_name):
        idx_name, idx_code = idx_code_name.split('   ')
        if item['dItem'] == '不包括当天':
            yes_or_no = True if option[f'{item["aItem"]}{bst}'] == [True] else False
            logStr = f"({idx_name}){item['bItem']}内(不包括当天) {item['cItem']}超过{item['itemValue']}% {'成立' if yes_or_no else '不成立'}"
            execStr = f'1==1' if yes_or_no else f'1==0'
        else:
            o = option[f'{item["aItem"]}{bst}'][0][0]  # x天前的开盘价
            o_udp = round((idx_data['close'] - o) / o * 100, 2)  # 最新价对比n天前的开盘价，幅度变化了多少

            a = item['bItem']
            b = item['itemValue']
            if item['cItem'] == '涨幅' and o_udp > float(b):
                logStr = f"({idx_name}){a}天(包括当天)前开盘价{o} {item['cItem']}超过{b}% ({o_udp}%) 成立"
                execStr = f'1==1'
            elif item['cItem'] == '跌幅' and o_udp < -float(b):
                logStr = f"({idx_name}){a}天(包括当天)前开盘价{o} {item['cItem']}超过{b}% ({o_udp}%) 成立"
                execStr = f'1==1'
            else:
                logStr = f"({idx_name}){a}天(包括当天)前开盘价{o} {item['cItem']}超过{b}% ({o_udp}%) 不成立"
                execStr = f'1==0'

        return execStr, logStr

    # 6.个股中历史涨/跌幅排名X
    def IDX_06(self, item, option, bst, idx_data, idx_code_name):
        idx_name, idx_code = idx_code_name.split('   ')
        o = option[f'{item["aItem"]}{bst}'][0]
        itemValue = item['itemValue']

        if item['bItem'] == '收盘涨幅' and idx_data['udp'] > o:
            logStr = f"({idx_name})收盘涨幅排名{int(itemValue)}的幅度{o}% ({idx_data['udp']}%) 成立"
            execStr = f'1==1'
        elif item['bItem'] == '收盘跌幅' and idx_data['udp'] < o:
            logStr = f"({idx_name})收盘跌幅排名{int(itemValue)}的幅度{o}% ({idx_data['udp']}%) 成立"
            execStr = f'1==1'
        elif item['bItem'] == '最大涨幅' and idx_data['udp'] > o:
            logStr = f"({idx_name})最大涨幅排名{int(itemValue)}的幅度{o}% ({idx_data['udp']}%) 成立"
            execStr = f'1==1'
        elif item['bItem'] == '最大跌幅' and idx_data['udp'] < o:
            logStr = f"({idx_name})最大跌幅排名{int(itemValue)}的幅度{o}% ({idx_data['udp']}%) 成立"
            execStr = f'1==1'
        else:
            logStr = f"({idx_name})历史{item['bItem']}排名{int(itemValue)}的幅度{o}% ({idx_data['udp']}%) 不成立"
            execStr = f'1==0'

        return execStr, logStr

    # 7.个股中达到历史最大涨/跌幅的XX%
    def IDX_07(self, item, option, bst, idx_data, idx_code_name):
        idx_name, idx_code = idx_code_name.split('   ')
        o = option[f'{item["aItem"]}{bst}'][0]
        itemValue = item['itemValue']

        if item['bItem'] == '最大涨幅' and idx_data['udp'] > o:
            logStr = f"({idx_name})历史最大涨幅的{itemValue}%为{o}% ({idx_data['udp']}%) 成立"
            execStr = f'1==1'
        elif item['bItem'] == '最大跌幅' and idx_data['udp'] < o:
            logStr = f"({idx_name})历史最大跌幅的{itemValue}%为{o}% ({idx_data['udp']}%) 成立"
            execStr = f'1==1'
        else:
            execStr = f'1==0'
            logStr = f"({idx_name})历史{item['bItem']}的{itemValue}%为{o}% ({idx_data['udp']}%) 不成立"
        return execStr, logStr

    # 8.XX指数跌同时XX指数涨
    def IDX_08(self, item, r, idx_data, idx_code_name):
        # idx_name, idx_code为bItem
        # cItem才是dItem
        idx_name, idx_code = idx_code_name.split('   ')
        name1, code1 = idx_name, idx_code
        name2, code2 = item['cItem'].split('   ')
        if r.hexists('idx_realMin', code2):
            idx_data2 = eval(r.hget('idx_realMin', code2))
            if item['cItem'] == '涨' and item['eItem'] == '跌':
                if idx_data['udp'] > 0 and idx_data2['udp'] < 0:
                    logStr = f"[{name1}]涨({idx_data['udp']}%)的同时[{name2}]跌({idx_data2['udp']}%) 成立"
                    execStr = f'1==1'
                else:
                    logStr = f"[{name1}]涨({idx_data['udp']}%)的同时[{name2}]跌({idx_data2['udp']}%) 不成立"
                    execStr = f'1==0'
            elif item['cItem'] == '跌' and item['eItem'] == '涨':
                if idx_data['udp'] < 0 and idx_data2['udp'] > 0:
                    logStr = f"[{name1}]跌({idx_data['udp']}%)的同时[{name2}]涨({idx_data2['udp']}%) 成立"
                    execStr = f'1==1'
                else:
                    logStr = f"[{name1}]跌({idx_data['udp']}%)的同时[{name2}]涨({idx_data2['udp']}%) 不成立"
                    execStr = f'1==0'
            else:
                logStr = f"指数涨跌选项相同{name1}{idx_data['udp']}% {name2}{idx_data2['udp']}%"
                execStr = f'1==0'
        else:
            logStr = f"{item['aItem']} 数据准备中"
            execStr = f'1==0'
        return execStr, logStr

    # 9.60秒跌幅XX%，XX秒涨幅XX%
    def IDX_09(self, item, idx_data, idx_code_name):
        if 'diff_v' not in idx_data:
            logStr = f"{item['aItem']} 数据准备中"
            execStr = f'1==0'
        else:
            udp_diff = idx_data['diff_v']
            idx_name, idx_code = idx_code_name.split('   ')
            if item['cItem'] == '涨':
                if udp_diff >= float(item['itemValue']):
                    logStr = f"({idx_name}){item['bItem']}秒{item['cItem']}幅{item['itemValue']}% ({round(udp_diff, 3)}%) 成立"
                    execStr = f'1==1'
                else:
                    logStr = f"({idx_name}){item['bItem']}秒{item['cItem']}幅{item['itemValue']}% ({round(udp_diff, 3)}%) 不成立"
                    execStr = f'1==0'
            elif item['cItem'] == '跌':
                if abs(udp_diff) >= float(item['itemValue']):
                    logStr = f"({idx_name}){item['bItem']}秒{item['cItem']}幅{item['itemValue']}% ({round(udp_diff, 3)}%) 成立"
                    execStr = f'1==1'
                else:
                    logStr = f"({idx_name}){item['bItem']}秒{item['cItem']}幅{item['itemValue']}% ({round(udp_diff, 3)}%) 不成立"
                    execStr = f'1==0'
            else:
                logStr = f"策略选项异常，请检查"
                execStr = f'1==0'
        return execStr, logStr

    # 其他1.亏损
    def OTHER_01(self, item, code, last_price, num, orderBuyPrice):
        item_pnl = -abs(float(item['itemValue']))

        # 盈亏金额 （实时价格 - 买入价格) * 股数
        one_pnle = (last_price - orderBuyPrice) * int(num)
        # 盈亏比率 盈亏金额/买入价格*股本 * 100%
        one_pnlfu = one_pnle / (orderBuyPrice * int(num)) * 100
        if len(code) > 10:
            one_pnle = one_pnle * 100
            one_pnlfu = one_pnlfu

        one_pnle = round(one_pnle, 3)  # 盈亏金额
        one_pnlfu = round(one_pnlfu, 3)  # 盈亏幅度

        if item_pnl < 0:
            if item['bItem'] == '金额':
                if one_pnle < item_pnl:
                    execStr = f'1==1'
                    logStr = f'亏损额度{item_pnl}({one_pnle}) √.(终止)'
                    return [True], logStr
                else:
                    execStr = f'1==0'
                    logStr = f'亏损额度{item_pnl}({one_pnle}) X.(终止)'
            elif item['bItem'] == '幅度':
                if one_pnlfu < item_pnl:
                    execStr = f'1==1'
                    logStr = f'亏损幅度{item_pnl}%({one_pnlfu}%) √.(终止)'
                    return [True], logStr
                else:
                    execStr = f'1==0'
                    logStr = f'亏损幅度{item_pnl}%({one_pnlfu}%) X.(终止)'
            else:
                logStr = f"策略选项异常，请检查"
                execStr = f'1==0'
        else:
            execStr = f'1==0'
            logStr = f'亏损不成立，当前盈利额度{one_pnle}, 盈利幅度{one_pnlfu} X.'
        return execStr, logStr

    # 其他2.有效期
    def OTHER_02(self, item, code,buyTime,ifSummer, trade_date_list,now_Time):
        if len(item['itemValue']) > 9:  # 旧版策略
            return [False], '旧版有效期策略错误'

        if code[:2] == 'HK':
            item_time = get_vail_sellTime_2(buyTime, trade_date_list, ifSummer, item,market='HK')
        else:
            item_time = get_vail_sellTime_2(buyTime, trade_date_list, ifSummer, item)

        if item_time is None:  # 跨1天卖出点比买入点小的情况
            logStr = f'有效期跨1天异常{str(now_Time)[:19]} ({item_time}) X.(终止)'
            execStr = f'1==0'
        else:
            if now_Time > item_time:
                logStr = f'达到有效期{str(now_Time)[:19]} ({item_time}) √.(终止)'
                return [True], logStr
            else:
                logStr = f'达到有效期{str(now_Time)[:19]} ({item_time}) X.(终止)'
                execStr = f'1==0'
        return execStr, logStr

    # 额外的补充
    def calc_pnl(self,code,last_price,orderBuyPrice,num):
        # 盈亏金额 （实时价格 - 买入价格) * 股数
        one_pnle = (last_price - orderBuyPrice) * int(num)
        # 盈亏比率 盈亏金额/买入价格*股本 * 100%
        one_pnlfu = one_pnle / (orderBuyPrice * int(num)) * 100
        if len(code) > 10:
            one_pnle = one_pnle * 100
            one_pnlfu = one_pnlfu

        one_pnle = round(one_pnle, 3)  # 盈亏金额
        one_pnlfu = round(one_pnlfu, 3)  # 盈亏幅度

        return one_pnle,one_pnlfu

    # 加载仓位缓存数据
    def position_data(self, r, code, price, prev_close_price, TrdEnv, acc_id):
        position_query = eval(r.hget('position_data_rs_tmp', TrdEnv + str(get_stock_type(code)) + acc_id))
        if code in position_query:
            # 'US.NIO': [127.0, 16.9103, 2.0, 39.21, 1.0, 19.66, '']
            qty = position_query[code][0]
            cost_price = position_query[code][1]
            today_buy_qty = position_query[code][2]
            today_buy_val = position_query[code][3]
            today_sell_qty = position_query[code][4]
            today_sell_val = position_query[code][5]

            if qty == 0:
                cal_pl_val = cal_pl_ratio = today_pl_val = qty = 0
            else:
                cal_pl_val = round((price - cost_price) * qty, 2)  # 盈亏金额=(现价-成本价)*股数
                cal_pl_ratio = round(cal_pl_val / (cost_price * abs(qty)) * 100, 2)  # 盈亏比例=  盈亏金额/(成本价*股数)
                if len(code) > 10:  # 期权
                    cal_pl_val *= 100

                # 今日盈亏=(今日市值-昨日市值)+(今日卖出均价-昨日收盘价)*今日卖出数量-(今日买入均价-昨日收盘价)*今日买入数量
                if len(code) > 10:  # 期权
                    sell_part = (today_sell_val / 100 / today_sell_qty - prev_close_price) * today_sell_qty * 100 if today_sell_qty != 0 else 0
                    buy_part = (today_buy_val / 100 / today_buy_qty - prev_close_price) * today_buy_qty * 100 if today_buy_qty != 0 else 0

                    today_pl_val = (price * qty * 100 - prev_close_price * qty * 100) + sell_part - buy_part
                else:
                    try:
                        sell_part = (today_sell_val / today_sell_qty - prev_close_price) * today_sell_qty if today_sell_qty != 0 else 0
                        buy_part = (today_buy_val / today_buy_qty - prev_close_price) * today_buy_qty if today_buy_qty != 0 else 0

                        today_pl_val = (price * qty - prev_close_price * qty) + sell_part - buy_part
                    except:
                        today_pl_val = 0

                today_pl_val = round(today_pl_val, 2)  # 今日持仓盈亏
        else:
            cal_pl_val = cal_pl_ratio = today_pl_val = qty = 0


        return cal_pl_val, cal_pl_ratio, today_pl_val, qty


def short_strategyt_group(data,option,now_Time,O_name,acc_id,ifSummer,TrdEnv,bst, number,code_name,cache_data,
                          cursor,r,buyPrice='',buyTime='',trade_date_list='',ifTest=False):


    if bst=='buy':
        itemList = option['buyItemList']
    elif bst=='sell':
        itemList = option['sellItemList']
    else:
        itemList = option['stopItemList']

    in_data = data
    in_code = data['code']
    # 美股非期权的成交额获取

    strategyFlagList = []
    logStrAll = []

    for i in eval(itemList[0]):
        # 判断是什么类型, 从而提取对应的data
        if len(in_code) > 10:
            if '正股' in i['aItem']:  # 期权+正股 用正股数据
                main_code = re.findall('(US\..*?)\d+.*?', in_code)[0]
                if main_code not in cache_data:  # 数据未订阅成功
                    return [False], f'{i["aItem"]} {main_code}数据准备中...'
                data = cache_data[main_code]  # 获取期权对应的正股缓存数据
            elif '个股对比' == i['aItem'].split(',')[0]:
                compare_code = i['bItem'].split(',')[1]
                if compare_code not in cache_data:  # 数据未订阅成功
                    return [False], '数据准备中...'

                data = cache_data[compare_code]
                if 'change_rate' not in data:
                    return [False], f'数据准备中...'

                i['bItem'] = i['cItem']  # 对item进行位移
                i['cItem'] = i['dItem']
                i['dItem'] = i['eItem']
            elif '指数' == i['aItem'].split(',')[0]:
                data = data
                idx_code_name = i['bItem']
                i['bItem'] = i['cItem']  # 对item进行位移
                i['cItem'] = i['dItem']
                i['dItem'] = i['eItem']

            else:  # 期权+期权 用自己本身数据
                data = in_data
        else:
            if '正股' == i['aItem'].split(',')[0]:  # 正股的正股 用自己本身数据
                data = in_data
            elif '个股对比' == i['aItem'].split(',')[0]:
                compare_code = i['bItem'].split(',')[1]
                if compare_code not in cache_data:  # 数据未订阅成功
                    return [False], f'{i["aItem"]} {compare_code}数据准备中...'

                data = cache_data[compare_code]
                if 'change_rate' not in data:
                    return [False], f'{i["aItem"]} 数据准备中...'

                i['bItem'] = i['cItem']  # 对item进行位移
                i['cItem'] = i['dItem']
                i['dItem'] = i['eItem']
            elif '指数' == i['aItem'].split(',')[0]:
                data = data
                idx_code_name = i['bItem']
                i['bItem'] = i['cItem']  # 对item进行位移
                i['cItem'] = i['dItem']
                i['dItem'] = i['eItem']

        try:
            S_code = data['code']
            price = data['last_price']
            high_price = data['high_price']
            low_price = data['low_price']
            UD = data['change']
            UDP = data['change_rate']
            preClose = data['prev_close_price']
            turnover = data['turnover']
            market_val = data['market_val']

        except Exception as e:
            print('eeeeeeeeee', data)
            return [False], f'{i["aItem"]} 数据准备中...{e}'

        # 不是指数
        if '其他' == i['aItem'].split(',')[0]:
            if i['aItem'] == '其他,亏损':
                execStr, logStr = Strategy_group().OTHER_01(i,S_code,price,number,buyPrice)
            elif i['aItem'] == '其他,有效期':
                execStr, logStr = Strategy_group().OTHER_02(i,S_code,buyTime,ifSummer,trade_date_list,now_Time)
            else:
                execStr = [False]
                logStr = f'{i["aItem"]} 策略不存在'

        elif '指数' != i['aItem'].split(',')[0]:
            if i['aItem'].split(',')[1] == '当前市价':
                execStr,logStr = Strategy_group().STK_01(i,price,high_price,low_price,code_name[S_code])
            elif i['aItem'].split(',')[1] == '市价涨跌':
                execStr, logStr = Strategy_group().STK_02(i,UD,UDP,code_name[S_code])
            elif i['aItem'].split(',')[1] == '成交额':
                execStr, logStr = Strategy_group(ifTest=ifTest).STK_03(i,S_code,turnover,r,code_name[S_code])
            elif i['aItem'].split(',')[1] == '单次盈亏':  # 正股/期权的单次盈亏
                execStr, logStr = Strategy_group().STK_04(i,S_code,price,number,buyPrice,O_name,code_name[in_code])
            elif i['aItem'].split(',')[1] == '持仓盈亏':
                execStr, logStr = Strategy_group().STK_05(i,r,S_code,price,preClose,TrdEnv,acc_id,code_name[S_code])
            elif i['aItem'].split(',')[1] == '今日持仓盈亏':
                execStr, logStr = Strategy_group().STK_06(i,r,S_code,price,preClose,TrdEnv,acc_id,code_name[S_code])
            elif i['aItem'].split(',')[1] == '时间':
                execStr, logStr = Strategy_group().STK_07(i,S_code,O_name,option,ifSummer,now_Time,code_name[S_code])
            elif i['aItem'].split(',')[1] == '市值':
                execStr, logStr = Strategy_group().STK_08(i,market_val,code_name[S_code])
            elif i['aItem'].split(',')[1] == '成交额变化':
                execStr, logStr = Strategy_group(ifTest=ifTest).STK_09(i,S_code,turnover,option,ifSummer,bst,cursor,now_Time,r,code_name[S_code])
            elif i['aItem'].split(',')[1] == '异动':
                execStr, logStr = Strategy_group().STK_10(i,S_code,r)
            elif i['aItem'].split(',')[1] == '成交额对比':
                execStr, logStr = Strategy_group(ifTest=ifTest).STK_11(i,in_code,S_code,in_data['turnover'],turnover,r,code_name)
            elif i['aItem'].split(',')[1] == '个股连涨/跌x天':
                execStr, logStr = Strategy_group().STK_new_01(i,option,bst,UDP)
            elif i['aItem'].split(',')[1] == '个股涨/跌X%后跌/涨X%':
                execStr, logStr = Strategy_group().STK_new_02(i,option,UDP,r)
            elif i['aItem'].split(',')[1] == 'XX股上涨/下跌比例X%':
                execStr, logStr = Strategy_group().STK_new_03(i,r,cache_data)
            elif i['aItem'].split(',')[1] == '大盘指数涨/跌X%后跌/涨X%':
                execStr, logStr = Strategy_group().STK_new_04(i,option,r,in_code,ifSummer,now_Time)
            elif i['aItem'].split(',')[1] == '历史最大/最高':
                execStr, logStr = Strategy_group().STK_new_06(i,option,bst,data)
            elif i['aItem'].split(',')[1] == 'X天内涨/跌幅超过XX%':
                execStr, logStr = Strategy_group().STK_new_07(i,option,bst,data)
            elif i['aItem'].split(',')[1] == '个股中历史涨/跌幅排名X':
                execStr, logStr = Strategy_group().STK_new_08(i,option,bst,data)
            elif i['aItem'].split(',')[1] == '个股中达到历史最大涨/跌幅的XX%':
                execStr, logStr = Strategy_group().STK_new_09(i,option,bst,data)
            elif i['aItem'].split(',')[1] == 'XX类股票跌同时XX类股票涨':
                execStr, logStr = Strategy_group().STK_new_10(i,cache_data,code_name,r)
            elif i['aItem'].split(',')[1] == 'XX个股涨/跌同时XX个股跌/涨':
                execStr, logStr = Strategy_group().STK_new_11(i,cache_data)
            elif i['aItem'].split(',')[1] == 'XX秒涨/跌幅XX%':
                execStr, logStr = Strategy_group().STK_new_12(i,option,now_Time,data,r)
            elif i['aItem'].split(',')[1] == '周期交易日':
                execStr, logStr = Strategy_group().STK_new_13(i,in_code,ifSummer,now_Time)
            else:
                execStr = [False]
                logStr = f'{i["aItem"]} 策略不存在'
        else:
            idx_name, idx_code = idx_code_name.split('   ')
            if not r.hexists('idx_realMin', idx_code):
                logStr = f'{idx_name} 数据准备中'
                execStr = f'1==0'
            else:
                idx_data = eval(r.hget('idx_realMin', idx_code))

                #  指数的固定值/涨跌幅，如恒生指数 大于xxx， 标普指数 涨跌幅1%
                # 测试通过
                if i['aItem'].split(',')[1] == '指数涨跌':
                    execStr, logStr = Strategy_group().IDX_01(i,ifSummer,now_Time,idx_data,idx_code_name)

                # 1.指数连涨/跌x天
                elif i['aItem'].split(',')[1] == '指数连涨/跌x天':
                    execStr, logStr = Strategy_group().IDX_02(i,option,bst,idx_data,idx_code_name)

                # 2.指数涨1 跌5
                elif i['aItem'].split(',')[1] == '指数涨/跌X%后跌/涨X%':
                    execStr, logStr = Strategy_group().IDX_03(i,option,idx_data,idx_code_name,r)

                # 3.历史最大/最高
                elif i['aItem'].split(',')[1] == '历史最大/最高':
                    execStr, logStr = Strategy_group().IDX_04(i,option,bst,idx_data,idx_code_name)

                # 7.X天内涨/跌幅超过XX%
                elif i['aItem'].split(',')[1] == 'X天内涨/跌幅超过XX%':
                    execStr, logStr = Strategy_group().IDX_05(i,option,bst,idx_data,idx_code_name)

                # 8.个股中历史涨/跌幅排名X
                elif i['aItem'].split(',')[1] == '指数中历史涨/跌幅排名X':
                    execStr, logStr = Strategy_group().IDX_06(i,option,bst,idx_data,idx_code_name)

                # 9.个股中达到历史最大涨/跌幅的XX%
                elif i['aItem'].split(',')[1] == '指数中达到历史最大涨/跌幅的XX%':
                    execStr, logStr = Strategy_group().IDX_07(i,option,bst,idx_data,idx_code_name)

                # 11.XX指数跌同时XX指数涨
                elif i['aItem'].split(',')[1] == 'XX指数涨/跌同时XX指数跌/涨':
                    execStr, logStr = Strategy_group().IDX_08(i,r,idx_data,idx_code_name)

                # 12.60秒跌幅XX%，XX秒涨幅XX%
                elif i['aItem'].split(',')[1] == '60秒涨/跌幅XX%':
                    execStr, logStr = Strategy_group().IDX_09(i,idx_data,idx_code_name)
                else:
                    execStr = [False]
                    logStr = f'{i["aItem"]} 策略不存在'

        # 首先是直接退出的 比如终止条件成立/策略异常
        if execStr==[True]:  # 配置项的2个单次盈亏，有效期，亏损
            return [True],logStr
        elif execStr==[False]:
            return [False], logStr
        else:
            # 剩下的才是计算策略是否合理
            if eval(execStr):
                strategyFlagList.append(True)
                logStrAll.append(logStr +'√.')
            else:
                strategyFlagList.append(False)
                logStrAll.append(logStr +'X.')


    # 是终止策略的时候，除去终止策略以外的普通策略单独判断是否组内and成立
    if bst=='stop':
        otherIndex = [x for x in range(len(logStrAll)) if '有效期' in logStrAll[x] or '亏损' in logStrAll[x]]  # 其他,策略的索引
        commonFlagList = [strategyFlagList[x] for x in range(len(strategyFlagList)) if x not in otherIndex]  # 终止条件的普通策略组
        if commonFlagList!=[] and all(commonFlagList):
            return [True], '</br>'.join(logStrAll)+'</br>'


    return strategyFlagList, '</br>'.join(logStrAll)+'</br>'

# 执行sql语句
def update_to_mysql(sql,cur,conn,ifCommit=False,ifTest=False):
    if ifTest==True:  # 只是测试则不用更新
        return
    cur.execute(sql)
    if ifCommit:
        conn.commit()


'''实时报价执行 短线逻辑'''
def shortRunStrategy(data, TrdEnv,if_summer,group, tbl_option,cache_data,code_name,
                    shortPosition,option_Detail, tbl_option_log, logger, trade_date_list,conn,r,shortList=[],optionDetailTmp='',shortPositionTmp='',ifTest=False):
    code = data['code']
    now = datetime.datetime.strptime(data["dt"], '%Y-%m-%d %H:%M:%S') if 'dt' in data \
        else datetime.datetime.strptime(data["data_date"] + ' ' + data["data_time"], '%Y-%m-%d %H:%M:%S')

    if 'US.' in code:
        now_time = (now + datetime.timedelta(hours=-12)) if if_summer else (now + datetime.timedelta(hours=-13))
        now_time = str(now_time.time())[:8]
    else:
        now_time = str(now.time())[:8]

    cursor = conn.cursor()
    if shortList == []:
        sql_option = f"select code,O_name,acc_id,dataModel from {tbl_option} where code='{code}' and (runState='等待执行' or runState='运行中') and (order_status='未下单' or order_status='全部已成') and `GROUP`={group} and `type`>0"
        cursor.execute(sql_option)
        option = [x for x in cursor.fetchall()]
    else:
        option = shortList

    if option != []:
        # 每一个策略加载对应的策略详情
        for c, O_name, acc_id, dataModel in option:
            # 测试
            if optionDetailTmp != '':
                optionDetail = optionDetailTmp
            else:
                if not r.hexists(option_Detail, f'{O_name}&&&{acc_id}'):
                    print('不存在', option_Detail, f'{O_name}&&&{acc_id}')
                    continue
                optionDetail = eval(r.hget(option_Detail, f'{O_name}&&&{acc_id}'))
                if not r.hexists('msg_shortOptions', f'{O_name}&&&{acc_id}'):
                    logger.info(f'msg_shortOptions还不存在 {O_name}&&&{acc_id}')
                    continue

            # 根据所选时段 确认接收数据的范围
            if 'US.' in code:
                if 'pre' in optionDetail and 'middle' not in optionDetail and 'after' not in optionDetail:  # 只选了 盘前
                    sd = '04:00:00'
                    ed = '09:30:00'
                elif 'pre' not in optionDetail and 'middle' in optionDetail and 'after' not in optionDetail:  # 只选了 盘中
                    sd = '09:30:01'  # 01秒的不要
                    ed = '16:00:00'
                elif 'pre' in optionDetail and 'middle' in optionDetail and 'after' not in optionDetail:  # 只选了 盘前+盘中
                    sd = '04:00:00'
                    ed = '16:00:00'
                elif 'pre' in optionDetail and 'middle' in optionDetail and 'after' in optionDetail:  # 只选了 盘前+盘中+盘后
                    sd = '04:00:00'
                    ed = '20:00:00'
                elif 'pre' not in optionDetail and 'middle' in optionDetail and 'after' in optionDetail:  # 只选了 盘中+盘后
                    sd = '09:30:01'  # 01秒的不要
                    ed = '20:00:00'
                elif 'pre' not in optionDetail and 'middle' not in optionDetail and 'after' not in optionDetail:  # 只选了 盘后
                    sd = '16:00:00'
                    ed = '20:00:00'
                else:
                    Except_stop(tbl_option, tbl_option_log, O_name, acc_id, '时段选择异常', cursor, conn, now, )
                    continue

                if not (sd <= now_time < ed):
                    continue

                if len(code) > 11 and ifTest == False:  # 避免期权被正股一直带动数据在盘后一直有数据写入
                    now_T = str(now.time())[:8]
                    if if_summer:
                        if now_T > '04:00:00' and now_T < '21:30:00':
                            continue
                    else:
                        if now_T > '05:00:00' and now_T < '22:30:00':
                            continue
            stock_numbers = float(optionDetail['stock_numbers'][0])

            # 持仓数据获取
            if shortPositionTmp == '':
                if not r.hexists(shortPosition, f'{O_name}&&&{acc_id}'):
                    continue
                # 判断当前持仓状态，决定买入卖出或持仓
                shortPosition_data = eval(r.hget(shortPosition, f'{O_name}&&&{acc_id}'))
            else:
                shortPosition_data = shortPositionTmp

            if len(shortPosition_data) == 1:
                order_direction = 0  # 买入
            else:  # 有持仓，卖出下单
                order_direction = 1

            # 买入成交价格
            if order_direction == 0:
                buy_order_price = ''
            else:
                try:
                    buy_order_price = shortPosition_data[4]
                except Exception as e:
                    error_msg = f"【持仓中获取买入价格异常】 {e.__traceback__.tb_frame.f_globals['__file__']} {e.__traceback__.tb_lineno} {traceback.print_exc()}"
                    logger.info(error_msg)
                    Except_stop(tbl_option, tbl_option_log, O_name, acc_id, error_msg, cursor, conn, now)
                    continue

            # 如果方向是卖，并且含有终止条件
            if order_direction == 1 and optionDetail['stopItemList'][0] != '[]':
                try:  # 异常处理 自动暂停，不影响其他策略
                    stopFlagList, stopLogStr = short_strategyt_group(data, optionDetail, now, O_name, acc_id, if_summer,
                                                                     TrdEnv, 'stop',
                                                                     stock_numbers, code_name, cache_data, cursor, r,
                                                                     buy_order_price, shortPosition_data[3],
                                                                     trade_date_list=trade_date_list, ifTest=ifTest)
                except Exception as e:
                    info = traceback.print_exc()
                    error_msg = f"【短线终止策略异常】 {info}"
                    logger.info(error_msg)
                    Except_stop(tbl_option, tbl_option_log, O_name, acc_id, error_msg, cursor, conn, now)
                    continue
            else:
                stopFlagList = []
                stopLogStr = ''

            # 买入/卖出策略
            try:
                bst = 'buy' if order_direction == 0 else 'sell'
                bsF, strategy = short_strategyt_group(data, optionDetail, now, O_name, acc_id, if_summer, TrdEnv, bst,
                                                      stock_numbers, code_name, cache_data, cursor, r, buy_order_price,
                                                      '', trade_date_list='', ifTest=ifTest)
            except Exception as e:
                error_msg = f"【短线买卖策略异常】 {e.__traceback__.tb_frame.f_globals['__file__']} {e.__traceback__.tb_lineno} {traceback.print_exc()}"
                logger.info(error_msg)
                Except_stop(tbl_option, tbl_option_log, O_name, acc_id, error_msg, cursor, conn, now)
                continue

            # 策略条件都成立，发送下单信号
            if (bsF != [] and all(bsF)) or (stopFlagList != [] and all(stopFlagList)):
                try:
                    logger.info(data)
                    logger.info(f'方向{"买入" if order_direction == 0 else "卖出"} {O_name} {strategy} {stopLogStr}')
                    if order_direction == 0:  # 买入信号
                        try:
                            # 买入条件达成，如果number_price是money则要重新计算stock_numbers，并更新optionDetail
                            if optionDetail['number_price'][0] == 'money':
                                if 'US.' in code and len(code) < 10:  # 美股正股
                                    stock_numbers = int(float(optionDetail['money'][0]) / data["last_price"])  # 向下取整
                                elif 'US.' in code and len(code) > 10:  # 美股期权
                                    stock_numbers = int(
                                        float(optionDetail['money'][0]) / data["last_price"] / 100)  # 向下取整
                                else:  # 港股 要根据最小股数进行整数倍的换算
                                    if 'lot_size' in optionDetail:
                                        stock_numbers = int(float(optionDetail['money'][0]) / data["last_price"] / int(
                                            optionDetail['lot_size'][0])) * int(optionDetail['lot_size'][0])
                                    else:
                                        stock_numbers = stock_numbers

                                # 更新到redis
                                optionDetail['stock_numbers'] = [str(stock_numbers)]
                                r.hset(option_Detail, f'{O_name}&&&{acc_id}', str(optionDetail))
                        except Exception as e:
                            sendEmail(f'money转数量异常{O_name} {acc_id} {TrdEnv}', str(e))
                            stock_numbers = stock_numbers

                        insert_sql = f'insert into {tbl_option_log} (`O_name`,`logTime`,`logPrice`,`logStr`,`acc_id`) VALUES ("{O_name}","{strTime_to_timestamp(now)}","{data["last_price"]}","【买入已下单，等待成交】</br>{strategy}","{acc_id}");'
                        update_to_mysql(insert_sql, cursor, conn, ifTest=ifTest)  # 写入sql

                        # 如果是不下单模式 就推送即可, 2次推送间隔要大于30秒
                        # if dataModel == 2:
                        #     msg_justRemind_buy(O_name, r, TrdEnv, code, code_name[code], data["last_price"],
                        #                        stock_numbers, round(data["last_price"] * stock_numbers, 2), acc_id,
                        #                        Model='Quote')
                        #     sql_tmp = f'UPDATE {tbl_option} set runState="运行中",number="{stock_numbers}",update_time={strTime_to_timestamp(now)} where O_name="{O_name}" and acc_id="{acc_id}"'
                        #     update_to_mysql(sql_tmp, cursor, conn, ifTest=ifTest)  # 写入sql
                        #     continue

                        # 更新mysql tbl_option的运行状态, 下单买入为等待成交状态
                        sql_tmp = f'UPDATE {tbl_option} set order_status="等待成交",order_status_2="满足买入条件",update_time={strTime_to_timestamp(now)} where O_name="{O_name}" and acc_id="{acc_id}"'
                        update_to_mysql(sql_tmp, cursor, conn, ifCommit=True, ifTest=ifTest)  # 写入sql

                        # 买入前读取上一次的累计盈亏，添加到买入的最后
                        cumul_pnl = shortPosition_data[-1]

                        # 更新redis缓存交易队列, 然后买入成交之后会在那边更新一次成交价格
                        r.hset(shortPosition, f'{O_name}&&&{acc_id}',
                               str(['shortOptionTrder', O_name, code, now, data["last_price"],
                                    stock_numbers, order_direction, strategy, TrdEnv, cumul_pnl]))

                        orderInfo = str(['shortOptionTrder', O_name, code, now, data["last_price"],
                                         stock_numbers, order_direction, '买入策略:' + strategy, acc_id, dataModel,
                                         TrdEnv])
                        r.lpush('orderQueue_s', orderInfo)

                    else:  # 卖出信号
                        if (bsF != [] and all(bsF)):
                            strategy = '卖出策略:' + str(strategy)
                        else:
                            strategy = '终止策略:' + str(stopLogStr)

                        # 如果是不下单模式 就推送即可, 2次推送间隔要大于30秒
                        if dataModel == 2:
                            tmp_pnl, tmp_pnl_p = Strategy_group().calc_pnl(code, data['last_price'], buy_order_price,
                                                                           stock_numbers)
                            # if all(bsF):
                            #     msg_justRemind_sell(O_name, r, TrdEnv, code, code_name[code], data["last_price"],
                            #                         stock_numbers,
                            #                         round(data["last_price"] * stock_numbers, 2), tmp_pnl_p, tmp_pnl,
                            #                         acc_id, Model='Quote')
                            # else:
                            #     msg_justRemind_stop(O_name, r, TrdEnv, code, code_name[code], data["last_price"],
                            #                         stock_numbers,
                            #                         round(data["last_price"] * stock_numbers, 2), tmp_pnl_p, tmp_pnl,
                            #                         acc_id, Model='Quote')
                            optionLog_sql = f'insert into {tbl_option_log}(`O_name`, `logTime`, `logPrice`, `logStr`, `acc_id`) values ("{O_name}","{strTime_to_timestamp(now)}","{data["last_price"]}","{strategy}","{acc_id}")'
                            update_to_mysql(optionLog_sql, cursor, conn, ifTest=ifTest)  # 写入sql

                            sql_tmp = f'UPDATE {tbl_option} set runState="运行中",update_time={strTime_to_timestamp(now)} where O_name="{O_name}" and acc_id="{acc_id}"'
                            update_to_mysql(sql_tmp, cursor, conn, ifTest=ifTest)  # 写入sql
                            continue

                        # 更新mysql tbl_option的运行状态, 下单卖出为等待成交状态
                        sql_tmp = f'UPDATE {tbl_option} set order_status="等待成交",order_status_2="满足卖出条件",update_time={strTime_to_timestamp(now)} where O_name="{O_name}" and acc_id="{acc_id}"'
                        update_to_mysql(sql_tmp, cursor, conn, ifCommit=True, ifTest=ifTest)  # 写入sql

                        insert_sql = f'insert into {tbl_option_log} (`O_name`,`logTime`,`logPrice`,`logStr`,`acc_id`) VALUES ("{O_name}","{strTime_to_timestamp(now)}","{data["last_price"]}","【卖出已下单，等待成交】</br>{strategy}","{acc_id}");'
                        update_to_mysql(insert_sql, cursor, conn, ifTest=ifTest)  # 写入sql

                        # 发送订单给redis
                        orderInfo = str(['shortOptionTrder', O_name, code, now, data["last_price"],
                                         stock_numbers, order_direction, strategy, acc_id, dataModel, TrdEnv])
                        r.lpush('orderQueue_s', orderInfo)
                except Exception as e:
                    error_msg = f"【短线条件达成异常】 {e.__traceback__.tb_frame.f_globals['__file__']} {e.__traceback__.tb_lineno} {traceback.print_exc()}"
                    print(error_msg, traceback.print_exc())
                    Except_stop(tbl_option, tbl_option_log, O_name, acc_id, error_msg, cursor, conn, now)
                    continue

                if ifTest:
                    return order_direction, orderInfo

            # 持仓为空条件直接失效
            elif strategy == '没有持仓不存在盈亏金额X.</br>':
                insert_sql = f'insert into {tbl_option_log} (`O_name`,`logTime`,`logPrice`,`logStr`,`acc_id`) VALUES ("{O_name}","{strTime_to_timestamp(now)}","{data["last_price"]}","条件执行失败，失败原因：{strategy}","{acc_id}");'
                update_to_mysql(insert_sql, cursor, conn, ifTest=ifTest)  # 写入sql

                sql_tmp = f'UPDATE {tbl_option} set runState="执行失败" where O_name="{O_name}" and acc_id="{acc_id}"'
                logger.info(f'没有持仓不存在盈亏金额X.</br> {sql_tmp}')
                update_to_mysql(sql_tmp, cursor, conn, ifTest=ifTest)  # 写入sql
            else:
                logStat = '【未持仓等待买入】' if order_direction == 0 else '【持仓中等待卖出】'
                sql_data = [0, O_name, strTime_to_timestamp(now), data["last_price"], '',
                            f'{logStat}</br>{strategy} {stopLogStr}', acc_id]

                sql_tmp = f'UPDATE {tbl_option} set runState="运行中",update_time={strTime_to_timestamp(now)} where O_name="{O_name}" and acc_id="{acc_id}"'
                update_to_mysql(sql_tmp, cursor, conn, ifTest=ifTest)  # 写入sql
                if ifTest == False:
                    r.rpush('option_short_logSql_S', str(sql_data))
        conn.commit()
        return None, ''


if __name__ == '__main__':
    pass
